<template>
  <div>
    <!-- v-model="visible" -->
    <!-- trigger="focus" -->
    <el-popover
      popper-class="vue_datepicker"
      v-model="show"
      trigger="manual"
      ref="popover"
      placement="right"
    >
      <el-input
        suffix-icon="el-icon-date"
        placeholder="请选择"
        @click.stop.native="show = !show"
        :value="value"
        @input="$emit('input', $event)"
        type="text"
        :readonly="readonly"
        size="small"
        slot="reference"
      />
      <div class="vue-datepicker-wrap">
        <div class="vue-datepicker-header" @click.stop="">
          <span @click.stop="switchMonth(-1)" class="el-icon-arrow-left"></span>
          <span
            @click.stop="selectYear = !selectYear"
            class="vue-datepicker-header-btn vue-datepicker-header-btn-day"
          >
            {{ select.year }} 年 {{ select.month }} 月
          </span>
          <span @click.stop="switchMonth(1)" class="el-icon-arrow-right"></span>
        </div>
        <div class="vue-datepicker-content p20">
          <table>
            <thead>
              <th>日</th>
              <th>一</th>
              <th>二</th>
              <th>三</th>
              <th>四</th>
              <th>五</th>
              <th>六</th>
            </thead>
            <tbody>
              <tr v-for="(week, index) of list" :key="index">
                <td
                  v-for="weekday of week"
                  @click="pick(weekday)"
                  :key="weekday.text + index"
                  :class="{
                    flag: weekday.flag,
                    active:
                      !weekday.flag &&
                      weekday.text == current.date &&
                      select.month == current.month &&
                      select.year == current.year,
                  }"
                >
                  {{ weekday.text }}
                </td>
              </tr>
            </tbody>
          </table>
          <div v-if="selectYear" class="vue-date-picker-year-panel">
            <ul ref="year">
              <li
                :key="index"
                v-for="(y, index) of years"
                @click.stop="pickYear(y)"
                :class="{ active: y == select.year }"
              >
                {{ y }}
              </li>
            </ul>
            <ul ref="month">
              <li
                :key="$index"
                v-for="(m, $index) of months"
                @click.stop="pickMonth($index + 1)"
                :class="{ active: $index + 1 == select.month }"
              >
                {{ m }}
              </li>
            </ul>
          </div>
        </div>
        <div class="time_box">
          <!-- <div class="time_num" v-if="currentTime">
            时间
            {{ currentTime | formatDate("HH:mm:ss") }}
          </div> -->
          <div class="time_num">时间 {{ tiemForm }}</div>
          <div class="now_text" @click="handNowTime">现在</div>
        </div>
        <div class="time_list p20">
          <div class="item">
            <div class="text">小时</div>
            <el-input-number
              v-model="form.hour"
              controls-position="right"
              :min="0"
              :max="24"
            ></el-input-number>
          </div>
          <div class="item">
            <div class="text">分钟</div>
            <el-input-number
              v-model="form.minute"
              controls-position="right"
              :min="0"
              :max="60"
            ></el-input-number>
          </div>
          <div class="item">
            <div class="text">秒</div>
            <el-input-number
              v-model="form.second"
              controls-position="right"
              :min="0"
              :max="60"
            ></el-input-number>
          </div>
          <div class="item">
            <div class="text">毫秒</div>
            <el-input-number
              v-model="form.millisecond"
              controls-position="right"
              :min="0"
              :max="999"
            ></el-input-number>
          </div>
        </div>
        <div class="btns">
          <div class="btn">取消</div>
          <div class="btn" @click="submit">确定</div>
        </div>
      </div>
    </el-popover>
  </div>
</template>

<script>
import moment from "moment";
export default {
  props: {
    readonly: {
      default: false,
      type: Boolean,
    },
    value: {},
    moment: {
      type: Number,
      default() {
        return new Date().getTime();
      },
    },
  },
  data() {
    return {
      upperVal: {},
      currentTime: 0,
      form: { hour: 0, millisecond: 0, second: 0, minute: 0 },
      show: false, // 控制日历面板的显示与隐藏
      selectYear: false, // 控制年份的面板的显示和隐藏
      current: "", // 已选择的日期时间。yyyy-MM-dd
      current2: "",
      select: {
        // 已选择的日期对象
        year: "",
        month: "",
        date: "",
        day: "",
      },
      currentMonthFirstDay: null, // 当前月的1号属于星期几
      currentMonthEndDate: null, // 当前月的最后一天是几号
      currentMonthEndDay: null, // 当前月的最后一天属于星期几
      lastMonthEndDate: null, // 上个月的最后一天是几号
      list: [], // 日历的二维数组
      years: [], // 1900-2100
      months: [
        "一月",
        "二月",
        "三月",
        "四月",
        "五月",
        "六月",
        "七月",
        "八月",
        "九月",
        "十月",
        "十一月",
        "十二月",
      ],
    };
  },
  computed: {
    tiemForm() {
      //   let { hour, minute, second, millisecond } = this.form;
      if (this.form.hour.toString().length >= 2) {
        this.form.hour = this.form.hour;
      } else {
        this.form.hour = "0" + this.form.hour;
      }
      if (this.form.minute.toString().length >= 2) {
        this.form.minute = this.form.minute;
      } else {
        this.form.minute = "0" + this.form.minute;
      }
      if (this.form.second.toString().length >= 2) {
        this.form.second = this.form.second;
      } else {
        this.form.second = "0" + this.form.second;
      }
      if (this.form.millisecond.toString().length >= 3) {
        this.form.millisecond = this.form.millisecond;
      } else if (this.form.millisecond.toString().length >= 2) {
        this.form.millisecond = "0" + this.form.millisecond;
      } else if (this.form.millisecond.toString().length >= 1) {
        this.form.millisecond = "00" + this.form.millisecond;
      }
      const time = `${this.form.hour}:${this.form.minute}:${this.form.second}.${this.form.millisecond}`;
      //   全部转成数字,不然加减按钮失效
      for (const key in this.form) {
        this.form[key] = Number(this.form[key]);
      }
      return time;
    },
  },
  watch: {
    select: {
      handler(newVal) {
        let pre;
        if (newVal.month == 1) {
          pre = new Date(newVal.year - 1, 12, 0);
        } else {
          pre = new Date(newVal.year, newVal.month - 1, 0);
        }
        this.lastMonthEndDate = pre.getDate();
        // 获取日历排表
        this.getDateList();
      },
      deep: true,
    },
    // value: {
    //   handler(newVal) {
    //     let val = new Date().getTime();
    //     if (newVal) {
    //       val = moment(Number(newVal)).format("YYYY-MM-DD");
    //     }

    //     this.transform(val);
    //     this.complete();
    //   },
    //   deep: true,
    // },
    show(newVal) {
      if (newVal) {
        let val = new Date().getTime();
        if (this.value) {
          // 修改默认选中-时分秒毫秒
          val = moment(Number(this.value)).format("YYYY-MM-DD");
          const date = new Date(Number(this.value));
          this.form.hour = date.getHours(); //获取当前小时数(0-23)
          this.form.minute = date.getMinutes(); //获取当前分钟数(0-59)
          this.form.second = date.getSeconds(); //获取当前秒数(0-59)
          this.form.millisecond = date.getMilliseconds(); //获取当前毫秒数(0-999)
        }

        this.transform(val);
        this.complete();
        document.addEventListener("click", this.bindEvent);
      } else {
        document.removeEventListener("click", this.bindEvent);
      }
    },
    // 打开年份选择器的时候使当前年份、月份出现在窗口顶部
    selectYear(newVal) {
      if (newVal) {
        this.$nextTick(() => {
          const year = this.$refs.year;
          const month = this.$refs.month;
          const y = year.getElementsByClassName("active")[0].innerHTML;
          const m = month.getElementsByClassName("active")[0].innerHTML;
          year.scrollTop = (y - 1900) * 30;
          month.scrollTop = (this.select.month - 1) * 30;
        });
      }
    },
  },
  created() {
    this.transform(this.moment);
    this.complete();
    // 获得年份列表： 1900-2100
    for (let i = 1900; i <= 2100; i++) {
      this.years.push(i);
    }
  },

  methods: {
    submit() {
      const { year, month, date } = this.current;
      const { hour, minute, second, millisecond } = this.form;
      const time = `${year}-${month}-${date} ${hour}:${minute}:${second}.${millisecond}`;
      const res = moment(time).valueOf();
      this.current2 = res;
      this.show = false;
      this.$emit("picked", this.current2);
      this.$emit("input", _.toString(this.current2));
      console.log(this.value, "====");
    },
    handNowTime() {
      this.currentTime = new Date();
      this.form.hour = this.currentTime.getHours(); //获取当前小时数(0-23)
      this.form.minute = this.currentTime.getMinutes(); //获取当前分钟数(0-59)
      this.form.second = this.currentTime.getSeconds(); //获取当前秒数(0-59)
      this.form.millisecond = this.currentTime.getMilliseconds(); //获取当前毫秒数(0-999)
    },
    /**
     * 将时间转化为具体的 年、月、日、星期
     **/
    transform(time) {
      const date = new Date(time);
      this.select.year = date.getFullYear();
      this.select.month = date.getMonth() + 1;
      this.select.date = date.getDate();
      this.select.day = date.getDay();

      this.currentMonthFirstDay = new Date(
        this.select.year,
        this.select.month - 1,
        1,
        0
      ).getDay();
      this.currentMonthEndDate = new Date(
        this.select.year,
        this.select.month,
        0
      ).getDate();
      this.currentMonthEndDay = new Date(
        this.select.year,
        this.select.month,
        0
      ).getDay();
    },
    /*
     * 计算出日历列表，二维数组
     * 第一层为星期，第二层为每星期的第几天
     */
    getDateList() {
      this.list = [];
      // 获取日历第一行的数据（需加上第一个星期中所包含上个月的几天）
      let temp = this.lastMonthEndDate - (this.currentMonthFirstDay - 1);
      let list = this.numberList(temp, this.lastMonthEndDate, true).concat(
        this.numberList(1, 7 - this.currentMonthFirstDay)
      );
      this.list.push(list);
      temp = 7 - this.currentMonthFirstDay + 1;

      /*
       * 剩下的行数
       */
      // 计算除了第一行剩下的天数
      const leftDays =
        this.currentMonthEndDate - (7 - this.currentMonthFirstDay);
      // 剩下的星期数
      const lineNumber = Math.ceil(leftDays / 7);
      // 包含下个月日历的天数
      const nextDays = 7 - (leftDays % 7);
      for (let i = 0; i < lineNumber; i++) {
        if (i === lineNumber - 1 && nextDays > 0 && nextDays !== 7) {
          this.list[lineNumber] = this.numberList(
            temp,
            this.currentMonthEndDate
          ).concat(this.numberList(1, nextDays, true));
        } else {
          this.list.push(this.numberList(temp, temp + 6));
        }
        temp = temp + 7;
      }
    },
    /*
     * 获得日历数组
     * start: 开始日
     * end: 结束日
     * flag： boolean值，判断是否属于本月
     */
    numberList(start, end, flag) {
      let list = [];
      for (let i = start; i <= end; i++) {
        list.push({
          text: i,
          flag: !!flag,
        });
      }
      return list;
    },
    /*
     * 切换月份， -1为当前月份-1，+1为当前月份+1
     */
    switchMonth(n) {
      let year = this.select.year;
      if (n === -1) {
        const pre = this.select.month === 1 ? 12 : this.select.month - 1;
        if (pre === 12) {
          this.transform(new Date(year - 1, pre - 1, this.select.date));
        } else {
          this.transform(new Date(year, pre - 1, this.select.date));
        }
      } else {
        const next = this.select.month === 12 ? 1 : this.select.month + 1;
        if (next === 1) {
          this.transform(new Date(year + 1, next - 1, this.select.date));
        } else {
          this.transform(new Date(year, next - 1, this.select.date));
        }
      }
    },
    pick(day) {
      if (!!day.flag) {
        // 当页日历上可能还会显示部分上个月或者下个月的部分天数，根据标识来做判断
        // 并对月份作出相应的处理
        if (parseInt(day.text) > 15) {
          this.transform(
            new Date(
              this.select.year,
              this.select.month - 2,
              parseInt(day.text)
            )
          );
        } else {
          this.transform(
            new Date(this.select.year, this.select.month, parseInt(day.text))
          );
        }
      } else {
        this.transform(
          new Date(this.select.year, this.select.month - 1, parseInt(day.text))
        );
      }
      this.complete();
    },
    // 绑定事件：点击关闭日历面板
    bindEvent() {
      this.show = false;
      this.selectYear = false;
    },
    // 选取年
    pickYear(n) {
      this.transform(new Date(n, this.select.month - 1, this.select.date));
      this.complete();
    },
    // 选取月
    pickMonth(n) {
      this.transform(new Date(this.select.year, n - 1, this.select.date));
      this.complete();
    },
    // 更改选中时间并向父组件派发事件
    complete() {
      // 触发父组件的传过来的picked事件。三个参数: 年，月，日
      //   this.$emit(
      //     "picked",
      //     this.select.year,
      //     this.select.month,
      //     this.select.date
      //   );
      this.current = {
        year: this.select.year,
        month: this.select.month,
        date: this.select.date,
      };
    },
  },
};
</script>

<style lang="scss" scoped>
.p20 {
  padding: 0 14px;
}
.vue_datepicker {
  padding: 0 !important;
  .btns {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    border-top: 1px solid rgba(0, 0, 0, 0.06);
    padding: 14px;
    /* padding-top: 16px; */
    /* margin-top: 16px; */
    .btn {
      color: #707070;
      font-size: 12px;
      cursor: pointer;
      &:last-child {
        color: #2680d2;
        margin-left: 24px;
      }
    }
  }
  .time_list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    .item {
      display: flex;
      align-items: center;
      flex-wrap: nowrap;
      width: 46%;
      margin-bottom: 14px;
      /deep/ .el-input-number.is-controls-right .el-input__inner {
        padding-left: 0;
        padding-right: 10px;
      }
      /deep/ .el-input-number {
        line-height: 24px;
      }
      /deep/ .el-input-number__increase {
        line-height: 12px !important;
        width: 12px !important;
      }
      /deep/ .el-input-number__decrease {
        width: 12px !important;
        line-height: 12px !important;
      }
      /deep/ .el-input__inner {
        height: 24px;
        line-height: 24px;
      }
      .text {
        white-space: nowrap;
        font-size: 12px;
        color: #666666;
        margin-right: 10px;
        min-width: 20px;
      }
    }
  }
  .time_box {
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-top: 1px solid rgba(0, 0, 0, 0.06);
    padding: 13px 14px;
    margin-top: 13px;
    .now_text {
      color: #2680d2;
      font-size: 12px;
      cursor: pointer;
    }
    .time_num {
      color: #666666;
      font-size: 12px;
    }
  }
  .vue-datepicker-wrap {
    width: 240px;
    /* box-shadow: 2px 2px 8px #bdb8b8; */
    z-index: 999;
    .vue-datepicker-header {
      padding: 0px 15px;
      font-size: 14px;
      text-align: center;
      line-height: 36px;
      border-bottom: 1px solid rgba(0, 0, 0, 0.06);
      display: flex;
      justify-content: space-between;
      align-items: center;
      .vue-datepicker-header-btn {
        cursor: pointer;
        &:hover {
          color: #008afe;
        }
      }
      .vue-datepicker-header-btn-pre {
        float: left;
      }
      .vue-datepicker-header-btn-day {
      }
      .vue-datepicker-header-btn-next {
        float: right;
      }
    }
    .vue-datepicker-content {
      position: relative;
      table {
        width: 100%;
        border-collapse: collapse;
        thead {
          line-height: 30px;
          font-size: 12px;
          th {
            text-align: center;
          }
          /* background: #eee; */
        }
        tbody {
          tr {
            line-height: 28px;
            td {
              font-size: 12px;
              text-align: center;
              cursor: pointer;
              &.active,
              &.active:hover {
                color: #fff;
                background: #2680d2;
              }
              &.flag {
                color: #999;
              }
            }
            td:hover {
              background: #e6f7ff;
            }
          }
        }
      }
      .vue-date-picker-year-panel {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: #fff;
        ul {
          width: 50%;
          height: 100%;
          margin: 0;
          padding-left: 0;
          box-sizing: border-box;
          overflow-y: auto;
          float: left;
          list-style: none;
          li {
            font-size: 14px;
            text-align: center;
            line-height: 30px;
            cursor: pointer;
            &.active {
              color: #fff;
              background: #007acc;
            }
          }
          &:first-child {
            border-right: 1px solid #007acc;
          }
        }
      }
    }
  }
}
</style>